package com.shihan.redis.springboot.demo.listener;

import com.shihan.redis.springboot.demo.entity.OrderNumberEntity;
import com.shihan.redis.springboot.demo.enums.OrderStatusEnum;
import com.shihan.redis.springboot.demo.mapper.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

/**
 * @Description redis key 过期监听的监听器类
 * @Author shihan
 * @Date 2021/1/23 19:47
 * @Version 1.0
 */
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

    @Autowired
    private OrderMapper orderMapper;

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    /**
     * 当 key 过期时，执行的回调方法（PS：包括启用内存阈值，配置淘汰策略后，被淘汰掉的 key，也会执行此处的回调方法）
     * TODO 疑问：现在能拿到过期的 key，但是对应的 value 可以拿到吗？
     * TODO 监听回调的方式还有待优化，考虑高并发时的场景应该怎么处理？ 思路：使用 多线程 或 MQ ！
     * @param message
     * @param pattern
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String key = message.toString();
        System.out.println("键 " + key + " 已失效！");

        // 监听回调，获取到 order_token 后的处理
        // TODO 这里是对所有的过期 key 进行监听回调，有没有什么办法进行归类划分呢？
        // 回答：目前的解决办法是，在给 key 命名时，做好规范
        //       这样就可以在回调这里通过 key 的命名来判断业务，进行划分处理！
        //       或者通过连接的 redis 库进行区分（在保存时，也得保持库的一致）！
        handelOrder(key);

    }

    private void handelOrder(String key) {
        System.out.println("注意：[" + key + "] 检查 order 是否支付，超过 30 秒未支付的，订单将失效！");
        // 1、通过 orderToken 查询订单详情；
        OrderNumberEntity orderByOrderToken = orderMapper.getOrderByOrderToken(key);

        if (orderByOrderToken == null) {
            return;
        }
        System.out.println("[" + key + "]" + orderByOrderToken);

        // 2、判断订单详情的状态；
        // 3、仍未支付，则设置订单状态为已废弃；
        if (orderByOrderToken.getOrderStatus() == OrderStatusEnum.ORDER_UN_PAY.getValue()) {
            // 0-未支付，1-已支付，2-已废弃
            orderByOrderToken.setOrderStatus(OrderStatusEnum.ORDER_ABORTED.getValue());
            orderMapper.updateOrderStatus(orderByOrderToken);
            System.out.println("[" + key + "] 订单未支付，已设置为废弃状态！");
            return;
        }

        System.out.println("[" + key + "] 订单成功支付！");

    }

}
